﻿using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using Ids4Review.AuthorizationServer.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Ids4Review.AuthorizationServer.Services
{
    public class ConsentService
    {
        private readonly IClientStore _clientStore;
        private readonly IResourceStore _resourceStore;
        private readonly IIdentityServerInteractionService _identityServerInteractionService;
        public ConsentService(IClientStore clientStore,
            IResourceStore resourceStore,
            IIdentityServerInteractionService identityServerInteractionService)
        {
            _clientStore = clientStore;
            _resourceStore = resourceStore;
            _identityServerInteractionService = identityServerInteractionService;
        }
        public async Task<ConsentVm> BuildConsentViewModelAsync(string returnUrl)
        {
            var request = await _identityServerInteractionService.GetAuthorizationContextAsync(returnUrl);
            if (request == null)
            {
                return null;
            }
            var resources = await _resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested);
            var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId);
            ConsentVm vm = CreateConsentVm(request, resources, client);
            return vm;
        }
        public async Task<ProcessGrantResult> ProcessGrantAsync(ConsentInputVm inputVm, string returnUrl = null)
        {
            var consentVm = await BuildConsentViewModelAsync(returnUrl);
            ProcessGrantResult rt = new ProcessGrantResult() { Success = false, Consent = consentVm, ReturnUrl = returnUrl };
            if (inputVm == null || string.IsNullOrEmpty(returnUrl))
            {
                throw new ArgumentNullException("Consent is  null or returnUrl is emptyOrNull.");
            }
            if (inputVm.Button.Equals("yes", StringComparison.OrdinalIgnoreCase))
            {
                ConsentResponse response = null;
                if (inputVm == null)
                {
                    response = ConsentResponse.Denied;
                }
                else
                {
                    response = new ConsentResponse()
                    {
                        RememberConsent = inputVm.RememberConsent,
                        ScopesConsented = inputVm.ScopesConsented
                    };
                    var request = await _identityServerInteractionService.GetAuthorizationContextAsync(returnUrl);
                    await _identityServerInteractionService.GrantConsentAsync(request, response, "1");
                    rt = new ProcessGrantResult() { Success = true, ReturnUrl = returnUrl };
                }
            }
            return rt;
        }
        #region Private internal methods.
        private ConsentVm CreateConsentVm(AuthorizationRequest request, Resources resources, Client client)
        {
            var vm = new ConsentVm()
            {
                ClientId = client.ClientId,
                ClientName = client.ClientName,
                ClientUrl = client.ClientUri,
                ClientLogoUrl = client.LogoUri,
                AllowRememeberConsent = client.AllowRememberConsent
            };
            var identityResources = resources.IdentityResources.Select(i => CreateScopeViewModel(i));
            var apiResources = resources.ApiResources.SelectMany(a => a.Scopes).Select(a => CreateScopeViewModel(a));
            vm.IdentityScopes.AddRange(identityResources);
            vm.ApiResources.AddRange(apiResources);
            return vm;
        }

        private ScopeVm CreateScopeViewModel(Scope a)
        {
            return new ScopeVm()
            {
                Name = a.Name,
                DisplayName = a.DisplayName,
                Description = a.Description,
                Emphasize = a.Emphasize,
                Required = a.Required,
                Checked = a.Required,
            };
        }

        private ScopeVm CreateScopeViewModel(IdentityResource i)
        {
            return new ScopeVm()
            {
                Name = i.Name,
                DisplayName = i.DisplayName,
                Description = i.Description,
                Emphasize = i.Emphasize,
                Required = i.Required,
                Checked = i.Required,
            };
        }
        #endregion
    }
}
